package com.ruoyi.common.utils.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class PingUtils {

    /**
     * 使用Java的InetAddress.isReachable方法检测主机是否可达
     * @param ipAddress IP地址或主机名
     * @param timeout 超时时间(毫秒)
     * @return 是否可达
     */
    public static boolean pingByInetAddress(String ipAddress, int timeout) {
        try {
            InetAddress inet = InetAddress.getByName(ipAddress);
            return inet.isReachable(timeout);
        } catch (UnknownHostException e) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 使用系统ping命令检测主机是否可达
     * @param ipAddress IP地址或主机名
     * @param pingCount ping次数
     * @param timeout 超时时间(秒)
     * @return 是否可达
     */
    public static boolean pingBySystemCommand(String ipAddress, int pingCount, int timeout) {
        String command;
        String os = System.getProperty("os.name").toLowerCase();

        // 根据不同操作系统构造不同的ping命令
        if (os.contains("win")) {
            command = "ping -n " + pingCount + " -w " + (timeout * 1000) + " " + ipAddress;
        } else {
            command = "ping -c " + pingCount + " -W " + timeout + " " + ipAddress;
        }

        try {
            Process process = Runtime.getRuntime().exec(command);
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                // 检查ping响应中是否包含"TTL"或"ttl"(Windows/Linux)
                if (line.toLowerCase().contains("ttl=") || line.toLowerCase().contains("ttl ")) {
                    return true;
                }
            }
            return false;
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 批量检测IP地址列表的连通性(多线程)
     * @param ipList IP地址列表
     * @param timeout 超时时间(毫秒)
     * @param useSystemCommand 是否使用系统ping命令
     * @return 可达的IP地址列表
     */
    public static List<String> batchPing(List<String> ipList, int timeout, boolean useSystemCommand) {
        List<String> reachableIps = new ArrayList<>();
        ExecutorService executor = Executors.newFixedThreadPool(20); // 使用线程池提高效率

        List<Callable<Boolean>> tasks = new ArrayList<>();
        for (String ip : ipList) {
            tasks.add(() -> {
                if (useSystemCommand) {
                    return pingBySystemCommand(ip, 2, timeout / 1000);
                } else {
                    return pingByInetAddress(ip, timeout);
                }
            });
        }

        try {
            List<Future<Boolean>> results = executor.invokeAll(tasks);
            for (int i = 0; i < results.size(); i++) {
                if (results.get(i).get()) {
                    reachableIps.add(ipList.get(i));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
        return reachableIps;
    }

    public static void main(String[] args) {
        // 示例：检测192.168.1.1到192.168.1.20的IP范围
        List<String> ipList = new ArrayList<>();
        for (int i = 1; i <= 20; i++) {
            ipList.add("192.168.1." + i);
        }

        System.out.println("使用InetAddress方式检测:");
        List<String> reachableIps1 = batchPing(ipList, 1000, false);
        System.out.println("可达设备: " + reachableIps1);

        System.out.println("\n使用系统ping命令检测:");
        List<String> reachableIps2 = batchPing(ipList, 1000, true);
        System.out.println("可达设备: " + reachableIps2);
    }
}